//
//  PLTextField.m
//
//  Created by KimmanYip on 2017/9/24.
//
//

#import "PLTextField.h"
#import "UIView+PLExtension.h"

static CGFloat kAnimationDuration = 0.3f;
static CGFloat kPlaceholderOriginalX = 10.f;

static CGFloat kTitleMargin = 20;

static CGFloat kBorderWidth = 1.0;

#pragma mark - PLBorderLayer

/**
 边框类
 */
@interface PLBorderLayer : CAShapeLayer

/**
 标题中心X坐标
 */
@property (nonatomic, assign) CGFloat titleCenterX;


/**
 标题宽度
 */
@property (nonatomic, assign) CGFloat titleLabelWidth;


@property (nonatomic, assign) CGFloat lineCornerRadius;

@end


@implementation PLBorderLayer

+ (BOOL)needsDisplayForKey:(NSString *)key {
    if ([key isEqualToString:@"titleLabelWidth"] ) {
        return YES;
    }
    return [super needsDisplayForKey:key];
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        // 默认边框颜色
        self.borderColor = [UIColor lightGrayColor].CGColor;
        // 处理圆角锯齿问题
        self.contentsScale = [[UIScreen mainScreen] scale];
    }
    return self;
}

- (instancetype)initWithLayer:(id)layer {
    if (self = [super initWithLayer:layer]) {
        PLBorderLayer *borderLayer = (PLBorderLayer *)layer;
        self.titleCenterX = borderLayer.titleCenterX;
        self.lineCornerRadius = borderLayer.lineCornerRadius;
    }
    return self;
}

- (void)drawInContext:(CGContextRef)ctx {
    
    CGFloat width = self.frame.size.width;
    CGFloat height = self.frame.size.height;
    
    // 为处理直线和圆弧接驳形成空白的偏移量
    CGFloat offset = 3.0;
    
    CGFloat startX = self.titleCenterX > self.lineCornerRadius ? self.titleCenterX : width*0.5;
    
    // 边框颜色
    CGContextSetStrokeColorWithColor(ctx, self.borderColor);
    
    // 圆角类设置
    // 线：右上
    CGContextMoveToPoint(ctx, startX+self.titleLabelWidth*0.5, 0);
    CGContextAddLineToPoint(ctx, width-self.lineCornerRadius+offset, 0);
    CGContextSetLineWidth(ctx, kBorderWidth);
    CGContextStrokePath(ctx);
    
    // 圆角：右上
    CGContextMoveToPoint(ctx, width-self.lineCornerRadius, 0);
    CGContextAddArcToPoint(ctx, width, 0, width, self.lineCornerRadius, self.lineCornerRadius);
    CGContextSetLineWidth(ctx, kBorderWidth*0.5);
    CGContextStrokePath(ctx);
    
    // 线：右
    CGContextMoveToPoint(ctx, width, self.lineCornerRadius-offset);
    CGContextAddLineToPoint(ctx, width, height-self.lineCornerRadius+offset);
    CGContextSetLineWidth(ctx, kBorderWidth);
    CGContextStrokePath(ctx);
    
    // 圆角：右下
    CGContextMoveToPoint(ctx, width, height-self.lineCornerRadius);
    CGContextAddArcToPoint(ctx, width, height, width-self.lineCornerRadius, height, self.lineCornerRadius);
    CGContextSetLineWidth(ctx, kBorderWidth*0.5);
    CGContextStrokePath(ctx);
    
    // 线：底
    CGContextMoveToPoint(ctx, width-self.lineCornerRadius+offset, height);
    CGContextAddLineToPoint(ctx, self.lineCornerRadius-offset, height);
    CGContextSetLineWidth(ctx, kBorderWidth);
    CGContextStrokePath(ctx);
    
    // 圆角：左下
    CGContextMoveToPoint(ctx, self.lineCornerRadius, height);
    CGContextAddArcToPoint(ctx, 0, height, 0, height-self.lineCornerRadius, self.lineCornerRadius);
    CGContextSetLineWidth(ctx, kBorderWidth*0.5);
    CGContextStrokePath(ctx);
    
    // 线：左
    CGContextMoveToPoint(ctx, 0, height-self.lineCornerRadius+offset);
    CGContextAddLineToPoint(ctx, 0, self.lineCornerRadius-offset);
    CGContextSetLineWidth(ctx, kBorderWidth);
    CGContextStrokePath(ctx);
    
    // 圆角：左上
    CGContextMoveToPoint(ctx, 0, self.lineCornerRadius);
    CGContextAddArcToPoint(ctx, 0, 0, self.lineCornerRadius, 0, self.lineCornerRadius);
    CGContextSetLineWidth(ctx, kBorderWidth*0.5);
    CGContextStrokePath(ctx);
    
    // 线：左上
    CGContextMoveToPoint(ctx, self.lineCornerRadius-offset, 0);
    CGContextAddLineToPoint(ctx, startX-self.titleLabelWidth*0.5, 0);
    CGContextSetLineWidth(ctx, kBorderWidth);
    CGContextStrokePath(ctx);
}

#pragma mark - Getter & Setter
- (void)setLineCornerRadius:(CGFloat)lineCornerRadius {
    CGFloat maxRadius = MIN(self.frame.size.width, self.frame.size.height) * 0.5;
    if (lineCornerRadius > maxRadius) {
        _lineCornerRadius = maxRadius;
    } else {
        _lineCornerRadius = lineCornerRadius;
    }
}

@end


#pragma mark -
#pragma mark - PLTextField

@interface PLTextField ()<UITextFieldDelegate>
{
    CGFloat _titleLabelWidth;
}

@property (nonatomic, strong) PLBorderLayer    *borderLayer;

@property (nonatomic, strong) UILabel           *placeholderLabel;


@end

@implementation PLTextField

#pragma mark - Life Cycle

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        
        [self setup];
        
        [[NSNotificationCenter defaultCenter] addObserverForName:UITextFieldTextDidBeginEditingNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
            if (note.object == self.textField) {
                [self setState:PLTextFieldStateEditing];
            }
        }];
        
        [[NSNotificationCenter defaultCenter] addObserverForName:UITextFieldTextDidEndEditingNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
            if (note.object == self.textField) {
                [self setState:PLTextFieldStateNormal];
            }
        }];
        
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    self.textField.frame = CGRectMake(10, 6, self.bounds.size.width - 20, self.bounds.size.height - 12);
    self.textField.textAlignment = self.textAlignment;
    
    self.borderLayer.frame = self.layer.bounds;
    self.borderLayer.lineCornerRadius = self.roundEdge ? self.frame.size.height * 0.5 : self.borderCornerRadius;
    
    [self setBolderProperty];
    
    [self updateplaceHolderCenter:[self holderLabelCenter]];
}


- (void)dealloc {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidEndEditingNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidBeginEditingNotification object:nil];
    
}

#pragma mark - Public Method
- (BOOL)resignFirstResponder {
    return [self.textField resignFirstResponder];
}

- (BOOL)becomeFirstResponder {
    return [self.textField becomeFirstResponder];
}

- (BOOL)isFirstResponder {
    return [self.textField isFirstResponder];
}

#pragma mark - Private Method
- (void)setup {
    
    // 默认颜色
    self.placeholderColor = [UIColor lightGrayColor];
    self.placeholderHighlightColor = [UIColor lightGrayColor];
    self.placeholderErrorColor = [UIColor redColor];
    
    [self.layer addSublayer:self.borderLayer];
    
    [self addSubview:self.placeholderLabel];
    [self addSubview:self.textField];
    
    self.minimumScaleFactor = 0.8f;
}


- (void)shakeAnimation {
    
    CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
    CGFloat currentTx = self.transform.tx;
    
    animation.duration = kAnimationDuration;
    animation.values = @[ @(currentTx), @(currentTx + 10), @(currentTx-8), @(currentTx + 8), @(currentTx -5), @(currentTx + 5), @(currentTx) ];
    animation.keyTimes = @[ @(0), @(0.225), @(0.425), @(0.6), @(0.75), @(0.875), @(1) ];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [self.borderLayer addAnimation:animation forKey:@"shake"];
    
}

- (void)minAnimation {
    [self setBolderProperty];
    _titleLabelWidth = self.borderLayer.titleLabelWidth;
    CABasicAnimation *startAnim = [CABasicAnimation animationWithKeyPath:@"titleLabelWidth"];
    startAnim.fromValue = @(.0f);
    startAnim.toValue = @(self.borderLayer.titleLabelWidth*0.5);
    startAnim.duration = kAnimationDuration;
    
    [self.borderLayer addAnimation:startAnim forKey:@"titleLabelWidth"];
    
    [UIView animateWithDuration:.5f animations:^{
        self.placeholderLabel.transform = CGAffineTransformMakeScale(self.minimumScaleFactor, self.minimumScaleFactor);
        [self updateplaceHolderCenter:[self holderLabelCenter]];
    } completion:nil];
}

- (void)maxAnimation {
    [self setBolderProperty];
    CABasicAnimation *startAnim = [CABasicAnimation animationWithKeyPath:@"titleLabelWidth"];
    startAnim.fromValue = @(_titleLabelWidth);
    startAnim.toValue = @(0.0f);
    startAnim.duration = kAnimationDuration;
    
    [self.borderLayer addAnimation:startAnim forKey:@"maxAnimation"];
    
    [UIView animateWithDuration:kAnimationDuration animations:^{
        self.placeholderLabel.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
        [self updateplaceHolderCenter:[self holderLabelCenter]];
    } completion:nil];
    
}

- (void)setBolderProperty {
    if (self.state == PLTextFieldStateEditing) {
        self.borderLayer.titleLabelWidth = self.minimumScaleFactor * self.placeholderLabel.width;
        // 设置边框线头与‘标题’的距离，两边，一边值为kTitleMargin
        self.borderLayer.titleLabelWidth += kTitleMargin*2;
    } else {
        self.borderLayer.titleLabelWidth = 0;
    }
    switch (self.textAlignment) {
        case NSTextAlignmentCenter:
        {
            self.borderLayer.titleCenterX = self.frame.size.width * 0.5;
        }
            break;
        default:
        {
            self.borderLayer.titleCenterX = kPlaceholderOriginalX+self.placeholderLabel.frame.size.width*0.5;
        }
            break;
    }
}


- (void)updateplaceHolderCenter:(CGPoint)center {
    self.placeholderLabel.center = center;
}

- (CGPoint)holderLabelCenter {
    
    CGPoint center = CGPointZero;
    
    switch (self.textAlignment) {
        case NSTextAlignmentCenter:
        {
            if (self.state == PLTextFieldStateEditing) {
                center = CGPointMake(self.frame.size.width*0.5, 0);
            } else {
                center = CGPointMake(self.frame.size.width*0.5, self.frame.size.height/2);
            }
        }
            break;
        default:
        {
            if (self.state == PLTextFieldStateEditing) {
                center = CGPointMake(kPlaceholderOriginalX+self.placeholderLabel.frame.size.width*0.5, 0);
            } else {
                center = CGPointMake(kPlaceholderOriginalX+self.placeholderLabel.frame.size.width*0.5, self.frame.size.height/2);
            }
        }
            break;
    }
    
    return center;
}

#pragma mark - Setters
- (void)setTextColor:(UIColor *)textColor {
    _textColor = textColor;
    self.textField.textColor = textColor;
}

- (void)setFont:(UIFont *)font {
    _font = font;
    self.textField.font = font;
    self.placeholderLabel.font = font;
    [self.placeholderLabel sizeToFit];
}

- (void)setClearButtonMode:(UITextFieldViewMode)clearButtonMode {
    _clearButtonMode = clearButtonMode;
    self.textField.clearButtonMode = clearButtonMode;
}

- (void)setTextAlignment:(NSTextAlignment)textAlignment {
    _textAlignment = textAlignment;
    self.textField.textAlignment = textAlignment;
    
    [self updateplaceHolderCenter:[self holderLabelCenter]];
    
    [self setNeedsDisplay];
}

- (void)setKeyboardType:(UIKeyboardType)keyboardType {
    _keyboardType = keyboardType;
    self.textField.keyboardType = keyboardType;
}

- (void)setSecureTextEntry:(BOOL)secureTextEntry {
    _secureTextEntry = secureTextEntry;
    self.textField.secureTextEntry = secureTextEntry;
}

- (void)setRoundEdge:(BOOL)roundEdge {
    _roundEdge = roundEdge;
}

- (void)setState:(PLTextFieldState)state {
    if (_state == state && state != PLTextFieldStateError) {
        return;
    }
    _state = state;
    switch (state) {
        case PLTextFieldStateNormal:
        {
            self.placeholderLabel.textColor = self.placeholderColor;
            self.borderLayer.borderColor = self.placeholderColor.CGColor;
            [self.borderLayer setNeedsDisplay];
            self.textField.text.length == 0 ? [self maxAnimation] : 0;
        }
            break;
        case PLTextFieldStateEditing:
        {
            self.placeholderLabel.textColor = self.placeholderHighlightColor;
            self.borderLayer.borderColor = self.placeholderHighlightColor.CGColor;
            [self.borderLayer setNeedsDisplay];
            self.textField.text.length == 0 ? [self minAnimation] : 0;
        }
            break;
        case PLTextFieldStateError:
        {
            self.placeholderLabel.textColor = self.placeholderErrorColor;
            self.borderLayer.borderColor = self.placeholderErrorColor.CGColor;
            [self.borderLayer setNeedsDisplay];
            [self shakeAnimation];
        }
            break;
        default:
            break;
    }
}

- (void)setDelegate:(id<UITextFieldDelegate>)delegate {
    _delegate = delegate;
    self.textField.delegate = delegate;
}

- (void)setBorderCornerRadius:(CGFloat)borderCornerRadius {
    _borderCornerRadius = borderCornerRadius;
    self.borderLayer.lineCornerRadius = borderCornerRadius;
}

- (void)setPlaceholderColor:(UIColor *)placeholderColor {
    _placeholderColor = placeholderColor;
    self.placeholderLabel.textColor = placeholderColor;
}

- (void)setPlaceholderHighlightColor:(UIColor *)placeholderHighlightColor {
    _placeholderHighlightColor = placeholderHighlightColor;
    self.placeholderLabel.highlightedTextColor = placeholderHighlightColor;
}

- (void)setPlaceholderErrorColor:(UIColor *)placeholderErrorColor {
    _placeholderErrorColor = placeholderErrorColor;
}

- (void)setAutocapitalizationType:(UITextAutocapitalizationType)autocapitalizationType {
    _autocapitalizationType = autocapitalizationType;
    self.textField.autocapitalizationType = autocapitalizationType;
}

- (void)setAutocorrectionType:(UITextAutocorrectionType)autocorrectionType {
    _autocorrectionType = autocorrectionType;
    self.textField.autocorrectionType = autocorrectionType;
}

- (void)setReturnKeyType:(UIReturnKeyType)returnKeyType {
    _returnKeyType = returnKeyType;
    self.textField.returnKeyType = returnKeyType;
}

- (void)setEnablesReturnKeyAutomatically:(BOOL)enablesReturnKeyAutomatically {
    _enablesReturnKeyAutomatically = enablesReturnKeyAutomatically;
    self.textField.enablesReturnKeyAutomatically = enablesReturnKeyAutomatically;
}

- (void)setPlaceholder:(NSString *)placeholder {
    _placeholder = [placeholder copy];
    self.placeholderLabel.text = placeholder;
    [self.placeholderLabel sizeToFit];
    [self updateplaceHolderCenter:[self holderLabelCenter]];
}

#pragma mark - Getters
- (NSString *)text {
    return [self.textField.text copy];
}

- (PLBorderLayer *)borderLayer {
    if (!_borderLayer) {
        _borderLayer = [PLBorderLayer layer];
        _borderLayer.frame = self.layer.bounds;

        [_borderLayer setNeedsDisplay];
    }
    return _borderLayer;
}

- (UILabel *)placeholderLabel {
    if (!_placeholderLabel) {
        _placeholderLabel = [UILabel new];
        _placeholderLabel.font = [UIFont systemFontOfSize:16];
        _placeholderLabel.textColor = [UIColor lightGrayColor];
        _placeholderLabel.highlightedTextColor = [UIColor greenColor];
    }
    return _placeholderLabel;
}

- (UITextField *)textField {
    if (!_textField) {
        _textField = [UITextField new];
    }
    return _textField;
}

- (void)setLeftView:(UIView *)leftView {
    _leftView = leftView;
    _textField.leftView = leftView;
}

- (void)setLeftViewMode:(UITextFieldViewMode)leftViewMode {
    _leftViewMode = leftViewMode;
    _textField.leftViewMode = leftViewMode;
}

- (void)setRightView:(UIView *)rightView {
    _rightView = rightView;
    _textField.rightView = rightView;
}

- (void)setRightViewMode:(UITextFieldViewMode)rightViewMode {
    _rightViewMode = rightViewMode;
    _textField.rightViewMode = rightViewMode;
}

@end
